/**
 * @Description:
 * @Author: cnHuaShao
 * @File:  OAuthApi
 * @Version: 1.0.0
 */

package api

import (
	"IdentityAuthentication/cmd/common/model"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-oauth2/oauth2/v4/errors"
	"github.com/go-oauth2/oauth2/v4/manage"
	"github.com/go-oauth2/oauth2/v4/models"
	"github.com/go-oauth2/oauth2/v4/server"
	"github.com/go-oauth2/oauth2/v4/store"
	oredis "github.com/go-oauth2/redis/v4"
	"github.com/go-redis/redis/v8"
	"github.com/google/uuid"
	"log"
	"net/http"
)

func init() {
	initOAuth()
}

/**
创建授权id与授权码
*/
func Credentials(c *gin.Context) {
	clientId := uuid.New().String()[:8]     // 生成一个客户端id
	clientSecret := uuid.New().String()[:8] // 生成一个客户端证书
	err := clientStore.Set(clientId, &models.Client{
		ID:     clientId,
		Secret: clientSecret,
		Domain: model.Conf.Http.HttpPort,
	})
	if err != nil {
		c.JSON(http.StatusBadRequest, model.Msg{
			"0x4000000",
			err.Error(),
			nil,
		})
		return
	}
	c.JSON(http.StatusOK, model.ReturnReqMess(model.MsgOK, map[string]string{
		"client_id":     clientId,
		"client_secret": clientSecret,
	}))
}

/**
获取授权token
*/
func Token(c *gin.Context) {
	srv.HandleTokenRequest(c.Writer, c.Request)
}

/**
授权
*/
func Authorize(c *gin.Context) {
	err := srv.HandleAuthorizeRequest(c.Writer, c.Request)
	if err != nil {
		c.JSON(http.StatusBadRequest, model.Msg{
			"0x400000",
			err.Error(),
			nil,
		})
	}
}

/**
验证授权
*/
func Verification(c *gin.Context) {
	_, err := srv.ValidationBearerToken(c.Request)
	if err != nil {
		c.JSON(http.StatusForbidden, model.Msg{
			"0x403000",
			err.Error(),
			nil,
		})
		c.Abort()
		return
	}
	c.Next()
}

var (
	clientStore *store.ClientStore
	srv         *server.Server
)

/**
初始OAuth2服务端
*/
func initOAuth() {
	mg := manage.NewDefaultManager()
	mg.SetAuthorizeCodeTokenCfg(manage.DefaultAuthorizeCodeTokenCfg) // 设置默认令牌基础参数，详见源码中注释
	// 1、存储token令牌
	switch model.Conf.Server.ServerType {
	case "redis":
		mg.MustTokenStorage(oredis.NewRedisStore(&redis.Options{
			Addr:     model.Conf.Redis.RedisIp + ":" + model.Conf.Redis.RedisPort,
			Password: model.Conf.Redis.RedisPwd,
			DB:       model.Conf.Redis.RedisDB,
		}), nil)
		break
	case "pg":
		break
	case "mysql":
		break
	case "ldap":
		break
	default:
		mg.MustTokenStorage(store.NewMemoryTokenStore())
	}
	// 2、客户端令牌存储
	clientStore = store.NewClientStore() // 创建客户端存储
	// 3、读取指定库中的数据，初始为客户端
	switch model.Conf.Server.ServerType {
	case "redis":
		// clientStore.Set()
		fmt.Println("11111111")
		break
	case "pg":
		break
	case "mysql":
		break
	case "ldap":
		break
	default:
		mg.MustTokenStorage(store.NewMemoryTokenStore())
		fmt.Println("2222222222222")
	}

	mg.MapClientStorage(clientStore) // 映射客户端存储接口
	// 3、创建一个默认的授权服务器
	srv = server.NewDefaultServer(mg)
	srv.SetAllowGetAccessRequest(true)                                  // 允许对令牌的GET请求
	srv.SetClientInfoHandler(server.ClientFormHandler)                  // 从请求中获取客户端信息，从表单中获取客户端数据 client_id  client_secret
	srv.SetInternalErrorHandler(func(err error) (re *errors.Response) { // 内部错误处理
		log.Println("内部错误：", err.Error())
		return
	})
	srv.SetResponseErrorHandler(func(re *errors.Response) {
		log.Println("响应错误：", re.Error.Error())
	})
}
